package com.wm.common.core.filter.base;

import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.wm.common.annotation.QueryFilter;
import com.wm.common.enums.FilterType;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;

@Slf4j
@Data
@Component
public class QueryWrapperContext<T> extends SearchContextBase {

    @JsonIgnore
    @JSONField(serialize = false)
    private QueryWrapper<T> selectCond = null;

    @JsonIgnore
    @JSONField(serialize = false)
    private Class<T> type;

    /**
     * 解析查询上下文中的参数，构建mybatis-plus分页对象
     * @return
     */
    @JsonIgnore
    @JSONField(serialize = false)
    public Page getPages(){
        Page page;
        List<OrderItem> orderList = new ArrayList<>();

        int currentPage=getPageable().getPageNumber();
        int pageSize=getPageable().getPageSize();

        //构造mybatis-plus分页
        if(StringUtils.isEmpty(currentPage) || StringUtils.isEmpty(pageSize))
            page=new Page(1,Short.MAX_VALUE);
        else
            page=new Page(currentPage + 1,pageSize);

        //构造mybatis-plus排序
        Sort sort = getPageable().getSort();
        Iterator<Sort.Order> it_sort = sort.iterator();

        if(ObjectUtils.isEmpty(it_sort))
            return page;

        while (it_sort.hasNext()) {
            Sort.Order sort_order = it_sort.next();
            String columnName = addTableAlias(getFieldColumnName(sort_order.getProperty()));
            if (!StringUtils.isEmpty(columnName)) {
                if(sort_order.getDirection() == Sort.Direction.ASC){
                    orderList.add(OrderItem.asc(columnName));
                }
                else if(sort_order.getDirection() == Sort.Direction.DESC){
                    orderList.add(OrderItem.desc(columnName));
                }
            }
        }
        if(!orderList.isEmpty()){
            page.setOrders(orderList);
        }

        return page;
    }

    /**
     * 获取QueryWrapper
     * @return
     */
    public QueryWrapper<T> getSelectCond() {
        if (selectCond == null) {
            parseQueryFilter();
        }

        return selectCond;
    }

    /**
     * 解析过滤条件
     */
    public void parseQueryFilter() {
        this.selectCond = new QueryWrapper<T>();

        Class<? extends QueryWrapperContext> contextClass = getClass();
        Field[] fields = contextClass.getDeclaredFields();

        for (Field field : fields) {
            QueryFilter annotation = field.getAnnotation(QueryFilter.class);
            field.setAccessible(true);
            try {
                if (annotation != null && !StringUtils.isEmpty(annotation.type())) {
                    if (!ObjectUtils.isEmpty(field.get(this))) {
                        String tableField = StringUtils.isEmpty(annotation.value()) ? getFieldColumnName(field.getName()) : annotation.value();

                        if (annotation.type() == FilterType.EQ) {
                            this.selectCond.eq(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                        if (annotation.type() == FilterType.NE) {
                            this.selectCond.ne(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                        if (annotation.type() == FilterType.LIKE) {
                            this.selectCond.like(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                        if (annotation.type() == FilterType.GT) {
                            this.selectCond.gt(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                        if (annotation.type() == FilterType.LT) {
                            this.selectCond.lt(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                        if (annotation.type() == FilterType.GE) {
                            this.selectCond.ge(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                        if (annotation.type() == FilterType.LE) {
                            this.selectCond.le(addTableAlias(tableField, annotation.alias()), field.get(this));
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                log.error("解析过滤条件异常！" + e.getMessage());
                e.printStackTrace();
            }

        }
    }

    /**
     * 添加别名
     * @param tableField
     * @return
     */
    public String addTableAlias(String tableField, String alias) {
        this.getType();
        if (StringUtils.isEmpty(alias)) {
            TableName annotation = type.getAnnotation(TableName.class);
            if (annotation != null) {
                return annotation.value() + "." + tableField;
            }
            return tableField;
        }
        return alias + "." + tableField;
    }

    /**
     * 添加别名，别名为表名称
     * @param tableField
     * @return
     */
    public String addTableAlias(String tableField) {
        return addTableAlias(tableField, null);
    }

    public Class<T> getType() {
        if (type == null) {
            ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
            type = (Class<T>)parameterizedType.getActualTypeArguments()[0];
        }
        return type;
    }

    public String getFieldColumnName(String fieldname) {
        this.getType();

        try {
            Field field = type.getDeclaredField(fieldname);
            if(field != null) {
                TableField tableField = field.getAnnotation(TableField.class);
                if(tableField != null && !StringUtils.isEmpty(tableField.value())) {
                    return tableField.value();
                }
            }
        } catch (NoSuchFieldException e) {
            log.error("未找到对应字段！");
            e.printStackTrace();
        }
        return null;
    }
}
